package euler

import Math._
import _root_.scalaSci.math.plot.plotTypes._
import _root_.scalaSci.math.plot.plot._
import _root_.scalaSci.math.plot.canvas._
import java.awt.Color
import java.util.Locale


object Probabilites {
	/*	val a = (8 * (Pi - 3)) / (3 * Pi * (4- Pi))
			val erf = new Function((it: Item) => new Item(signum(it.d) * sqrt(1 - exp((0-1)*(it.d*it.d) *(((4/Pi) + (it.d*it.d*a)) / (1 + (it.d*it.d*a)))))),"erf")*/
}

/*
 * http://fr.wikipedia.org/wiki/Loi_normale
 * http://fr.wikipedia.org/wiki/%C3%89cart_type
 * http://fr.wikipedia.org/wiki/Loi_de_Bernoulli
 * http://fr.wikipedia.org/wiki/Loi_binomiale
 * http://math.univ-lille1.fr/~suquet/ens/ICP/Cmd060902.pdf
 * http://cermics.enpc.fr/~jourdain/probastat/poly.pdf
 * http://www.physics.ohio-state.edu/~gan/teaching/spring04/Chapter3.pdf
 */


class Gauss(val sigma: Double, val mu: Double) {
	val gauss = new Function((it: Item) => new Item((1/(sigma*sqrt(2*scala.math.Pi)))*pow(E,(0-1)*(it.d-mu)*(it.d-mu)/(2*sigma*sigma))),"gauss(sigma: %4.3f".format(sigma)+", mu: "+mu+")")
	//val PHI = new Function((it: Item) => new Item(0.5+((1/sqrt(2*Pi))*(it.d-(it.d*it.d*it.d/6)+(it.d*it.d*it.d*it.d*it.d/40)))),"PHI(sigma: "+sigma+", mu: "+mu+")")
	val PHI = new Function((it: Item) => new Item(GaussPhi.getVal(it.d)*sigma),"PHI(sigma: %4.3f".format(sigma)+", mu: "+mu+")")
	//	val PHI = new Function((it: Item) => new Item(0.5+Probabilites.erf.process(new Item(it.d/sqrt(2))).d),"PHI2(sigma: "+sigma+", mu: "+mu+")")

	def printTable(fs: List[Function]) = {
		println(fs.mkString(" -*- "))
		new Range(0,40,2).toList.foreach((i: Int) => {
			val d = i.toDouble/10.0
					println("  %4.3f ".format(d)+fs.map((f: Function) => f.process(new Item(d))+" "))
		})
	}

	def find(f: Function, in: (Double,Double,Double)): (Double,Double,Double) = {
		//println("find [%4.3f] in [".format(in._1)+f+"] "+in)
		if(abs(in._2-in._3)<0.0000001) {
			in
		} else {
			val y32 = (in._3+in._2)/2.0
					val z = f.process(new Item(in._2)).d
					val y = f.process(new Item(y32)).d
					val x = f.process(new Item(in._3)).d
					/*println("  "+f+"  in: "+in+" %4.3f".format(in._2)+"/x: %4.3f".format(x)+
							" %4.3f".format(y32)+"/y: %4.3f".format(y)+" %4.3f".format(in._3)+"/z: %4.3f".format(z))*/
					if((in._1>x)&(in._1<y)) {
						find(f,(in._1,y32,in._3))
					} else if((in._1>y)&(in._1<z)) {
						find(f,(in._1,in._2,y32))
					} else if((in._1<y)&(in._1>z)) {
						find(f,(in._1,in._2,y32))
					} else if((in._1<x)&(in._1>y)) {
						find(f,(in._1,y32,in._3))
					} else {
						require(false, f+"  in: "+in+" %4.3f".format(in._2)+"/x: %4.3f".format(x)+
								" %4.3f".format(y32)+"/y: %4.3f".format(y)+" %4.3f".format(in._3)+"/z: %4.3f".format(z))
								in
					}
		}
	}

	def dessine(fs: List[Function], range: Range, inc: Double) = {
		figure()
		title(fs.mkString(" -*- "))
		linePlotsOn
		val x = range.toList.map((i: Int) => i.toDouble*inc)
		var hue = 0.1.toFloat
		val incHue = 1.0.toFloat/fs.size
		fs.foreach((f: Function) => {
			val y = x.map((d: Double) => f.process(new Item(d)).d)
					plot(x.toArray, y.toArray, MyPlotUtils.getColor(hue),f.toString)
					hue += incHue
		})
	}
}

class Bernouilli(val p: Double, mu: Double) extends Gauss(Math.sqrt(p*(1-p)),mu){
	assume(p>0.0)
	assume(p<1.0)
	override val gauss = new Function((it: Item) => new Item((1/(sigma*sqrt(2*scala.math.Pi)))*pow(E,(0-1)*(it.d-mu)*(it.d-mu)/(2*sigma*sigma))),
	"bernouilli(p: "+p+", mu: "+mu+") sigma: %4.3f".format(sigma))
}

class Binomiale(val p: Double, val n: Int) extends Gauss(Math.sqrt(n*p*(1-p)),n*p){
	assume(p>0.0)
	assume(p<1.0)
	assume(n>0)
	override val gauss = new Function((it: Item) => new Item((1/(sigma*sqrt(2*scala.math.Pi)))*pow(E,(0-1)*(it.d-mu)*(it.d-mu)/(2*sigma*sigma))),
	"binomiale(p: "+p+", n: "+n+", mu: "+mu+") sigma: %4.3f".format(sigma))
}

object GaussPhi {
	def getVal(x: Double) = {
		assume(x>=0.0,x+" >= 0.0")
		assume(x<4.0,x+" < 4.0")
		Locale.setDefault(Locale.US)
		val s = "%4.3f".format(x)
		val t = s.substring(0,4).toDouble
		val i = (t/0.01).toInt
		val v = l.apply(i)
		val w = l.apply(i+1)
		val r = (x-t)*100
		val y = r*(w-v)
		//println("x: "+x+" t: "+t+" v: "+v+" w. "+w+" r: "+r+" y: "+y)
		v+y
	}

	// http://fr.wikipedia.org/wiki/Loi_normale
	val l = List(
			0.50000, 0.50399, 0.50798, 0.51197, 0.51595, 0.51994, 0.52392, 0.52790, 0.53188, 0.53586,
			0.53983, 0.54380, 0.54776, 0.55172, 0.55567, 0.55962, 0.56356, 0.56749, 0.57142, 0.57535,
			0.57926, 0.58317, 0.58706, 0.59095, 0.59483, 0.59871, 0.60257, 0.60642, 0.61026, 0.61409,
			0.61791, 0.62172, 0.62552, 0.62930, 0.63307, 0.63683, 0.64058, 0.64431, 0.64803, 0.65173,
			0.65542, 0.65910, 0.66276, 0.66640, 0.67003, 0.67364, 0.67724, 0.68082, 0.68439, 0.68793,
			0.69146, 0.69497, 0.69847, 0.70194, 0.70540, 0.70884, 0.71226, 0.71566, 0.71904, 0.72240,
			0.72575, 0.72907, 0.73237, 0.73565, 0.73891, 0.74215, 0.74537, 0.74857, 0.75175, 0.75490,
			0.75804, 0.76115, 0.76424, 0.76730, 0.77035, 0.77337, 0.77637, 0.77935, 0.78230, 0.78524,
			0.78814, 0.79103, 0.79389, 0.79673, 0.79955, 0.80234, 0.80511, 0.80785, 0.81057, 0.81327,
			0.81594, 0.81859, 0.82121, 0.82381, 0.82639, 0.82894, 0.83147, 0.83398, 0.83646, 0.83891,
			0.84134, 0.84375, 0.84614, 0.84849, 0.85083, 0.85314, 0.85543, 0.85769, 0.85993, 0.86214,
			0.86433, 0.86650, 0.86864, 0.87076, 0.87286, 0.87493, 0.87698, 0.87900, 0.88100, 0.88298,
			0.88493, 0.88686, 0.88877, 0.89065, 0.89251, 0.89435, 0.89617, 0.89796, 0.89973, 0.90147,
			0.90320, 0.90490, 0.90658, 0.90824, 0.90988, 0.91149, 0.91309, 0.91466, 0.91621, 0.91774,
			0.91924, 0.92073, 0.92220, 0.92364, 0.92507, 0.92647, 0.92785, 0.92922, 0.93056, 0.93189,
			0.93319, 0.93448, 0.93574, 0.93699, 0.93822, 0.93943, 0.94062, 0.94179, 0.94295, 0.94408,
			0.94520, 0.94630, 0.94738, 0.94845, 0.94950, 0.95053, 0.95154, 0.95254, 0.95352, 0.95449,
			0.95543, 0.95637, 0.95728, 0.95818, 0.95907, 0.95994, 0.96080, 0.96164, 0.96246, 0.96327,
			0.96407, 0.96485, 0.96562, 0.96638, 0.96712, 0.96784, 0.96856, 0.96926, 0.96995, 0.97062,
			0.97128, 0.97193, 0.97257, 0.97320, 0.97381, 0.97441, 0.97500, 0.97558, 0.97615, 0.97670,
			0.97725, 0.97778, 0.97831, 0.97882, 0.97932, 0.97982, 0.98030, 0.98077, 0.98124, 0.98169,
			0.98214, 0.98257, 0.98300, 0.98341, 0.98382, 0.98422, 0.98461, 0.98500, 0.98537, 0.98574,
			0.98610, 0.98645, 0.98679, 0.98713, 0.98745, 0.98778, 0.98809, 0.98840, 0.98870, 0.98899,
			0.98928, 0.98956, 0.98983, 0.99010, 0.99036, 0.99061, 0.99086, 0.99111, 0.99134, 0.99158,
			0.99180, 0.99202, 0.99224, 0.99245, 0.99266, 0.99286, 0.99305, 0.99324, 0.99343, 0.99361,
			0.99379, 0.99396, 0.99413, 0.99430, 0.99446, 0.99461, 0.99477, 0.99492, 0.99506, 0.99520,
			0.99534, 0.99547, 0.99560, 0.99573, 0.99585, 0.99598, 0.99609, 0.99621, 0.99632, 0.99643,
			0.99653, 0.99664, 0.99674, 0.99683, 0.99693, 0.99702, 0.99711, 0.99720, 0.99728, 0.99736,
			0.99744, 0.99752, 0.99760, 0.99767, 0.99774, 0.99781, 0.99788, 0.99795, 0.99801, 0.99807,
			0.99813, 0.99819, 0.99825, 0.99831, 0.99836, 0.99841, 0.99846, 0.99851, 0.99856, 0.99861,
			0.99865, 0.99869, 0.99874, 0.99878, 0.99882, 0.99886, 0.99889, 0.99893, 0.99896, 0.99900,
			0.99903, 0.99906, 0.99910, 0.99913, 0.99916, 0.99918, 0.99921, 0.99924, 0.99926, 0.99929,
			0.99931, 0.99934, 0.99936, 0.99938, 0.99940, 0.99942, 0.99944, 0.99946, 0.99948, 0.99950,
			0.99952, 0.99953, 0.99955, 0.99957, 0.99958, 0.99960, 0.99961, 0.99962, 0.99964, 0.99965,
			0.99966, 0.99968, 0.99969, 0.99970, 0.99971, 0.99972, 0.99973, 0.99974, 0.99975, 0.99976,
			0.99977, 0.99978, 0.99978, 0.99979, 0.99980, 0.99981, 0.99981, 0.99982, 0.99983, 0.99983,
			0.99984, 0.99985, 0.99985, 0.99986, 0.99986, 0.99987, 0.99987, 0.99988, 0.99988, 0.99989,
			0.99989, 0.99990, 0.99990, 0.99990, 0.99991, 0.99992, 0.99992, 0.99992, 0.99992, 0.99992,
			0.99993, 0.99993, 0.99993, 0.99994, 0.99994, 0.99994, 0.99994, 0.99995, 0.99995, 0.99995,
			0.99995, 0.99995, 0.99996, 0.99996, 0.99996, 0.99996, 0.99996, 0.99996, 0.99997, 0.99997    
			)

}
